/*******************************************************************************
 * Copyright (c) 2014 Greg Marut.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the GNU Public License v3.0
 * which accompanies this distribution, and is available at
 * http://www.gnu.org/licenses/gpl.html
 * 
 * Contributors:
 *    Greg Marut - initial API and implementation
 ******************************************************************************/
package com.gregmarut.serialization;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import com.gregmarut.util.Log;

/**
 * @author Greg Marut
 * @param <T>
 */
public class DefaultSerializer implements Serializer
{
	/**
	 * The constructor for Serializer
	 */
	public DefaultSerializer()
	{
		
	}
	
	/**
	 * Converts a Serializable object to a byte array
	 * 
	 * @param serializable
	 * @return
	 */
	@Override
	public byte[] flattenObject(final Serializable serializable) throws IOException
	{
		// holds the array of bytes to return
		byte[] bytes = null;
		
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		ObjectOutputStream oos = new ObjectOutputStream(baos);
		oos.writeObject(serializable);
		oos.close();
		
		// Get the bytes of the serialized object
		bytes = baos.toByteArray();
		
		// return the array of bytes
		return bytes;
	}
	
	/**
	 * Restores an object to its original object from a serialized array of
	 * bytes
	 * 
	 * @param bytes
	 * @param clazz
	 * @return
	 * @throws SerializationException
	 */
	@SuppressWarnings("unchecked")
	@Override
	public <T extends Serializable> T restoreObject(final byte[] bytes, final Class<T> clazz) throws SerializationException
	{
		// holds the object to return of type E
		T result;
		
		try
		{
			// decode the body
			ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
			ObjectInputStream ois = new ObjectInputStream(bais);
			result = (T) ois.readObject();
			ois.close();
		}
		catch (ArrayIndexOutOfBoundsException e)
		{
			// make sure the logger should display this error
			if (Log.DISPLAY_INTERNAL_ERRORS)
			{
				// log the error
				Log.err(e);
			}
			
			throw new SerializationException(e);
		}
		catch (IOException e)
		{
			// make sure the logger should display this error
			if (Log.DISPLAY_INTERNAL_ERRORS)
			{
				// log the error
				Log.err(e);
			}
			
			throw new SerializationException(e);
		}
		catch (ClassNotFoundException e)
		{
			// make sure the logger should display this error
			if (Log.DISPLAY_INTERNAL_ERRORS)
			{
				// log the error
				Log.err(e);
			}
			
			throw new SerializationException(e);
		}
		
		// return the restored object
		return result;
	}
}
